﻿/*
 * DataLegendNodeBase
 * 
 * initial implementation : 12.12.2008
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;
using System.Collections.Generic;
using Petra.Gis.DataServices;
using Petra.Gis.DataServices.Metadata;
using Petra.Gis.ReferenceSystemServices.Transformations;


namespace Petra.Gis.RenderingServices.PlanarBase
{


  /// <summary>
  /// Legend node which can contain data
  /// and render this data into map at output format using renderers
  /// </summary>
  public abstract class DataLegendNodeBase : RenderableLegendNodeBase
  {

    /// <summary>
    /// indicates whether <c>DataLegendNodeBase</c> uses GIS feature attributes
    /// to display feature with variable style depending on <c>VisualAttribute</c> value
    /// </summary>
    protected bool _hasVisualAttributes;


    #region ctor

    protected DataLegendNodeBase()
      :base()
    {
      VisualAttributes = new DataVisualAttributes();
      Renderers = new RendererList(this);
    }




    protected DataLegendNodeBase(LeafLegendNode parent, string title)
      : base(parent, title)
    {
      VisualAttributes = new DataVisualAttributes(); 
      Renderers = new RendererList(this);
    }

    #endregion ctor




    private RendererList _renderers;

    //public abstract RendererList Renderers { get; set; }

    /// <summary>
    /// get/set List of renderers used to render GIS Feature in map
    /// </summary>
    public RendererList Renderers
    {
      get { return _renderers; }
      set
      {
        if (value == null)
          throw new ArgumentException("null renderers invalid");

        _renderers = value;
        prepareRenders();
      }
    }





    protected virtual void validateIFeatureSet(IFeatureSet value)
    {
      if (value == null)
        throw new ArgumentException("featureSet is null");

      if (value.Metadata == null)
        throw new ArgumentException("invalid input, missing feature metadata");

      if (value.Metadata.GeometryFieldsMetadata.Length < 1)
        throw new ArgumentException("invalid command, no geometries found, cant render into map and legend");

      prepareRenders();
    }





    //protected abstract void validateRenderers();





    //protected DataVisualAttributes _visualAttributes;

    /// <summary>
    /// returns collection of user defined attribute names
    /// parsed from Renderer and Render.Style
    /// these attributes must exit in data source otherwise
    /// renderer will throw error
    /// value part of this collection holds current Attribute (Field) value(s)
    /// </summary>
    public virtual DataVisualAttributes VisualAttributes
    { get; set; }





    protected virtual void prepareRenders()
    {
      // if no metadata exit
      if (featureSet.Metadata == null)
        return;

      FeatureMetadata _metadata = featureSet.Metadata;

      if (_metadata.GeometryFieldsMetadata.Length < 1)
        throw new ArgumentException("invalid input metadata or FeatureSet, no geometry");

      //if feature set has more geometry fields
      //, check if all renderers has assigned some geom. field
      if (_metadata.GeometryFieldsMetadata.Length > 1)
      {
        foreach (RendererBase r in _renderers)
          if (r.SpatialFieldName == "")
            throw new ArgumentException("no spatial field name specified in renderer." + r.GetType().ToString());
      }

      //// if feature has more than 1 geometry field
      //// each renderer must have expose name of field to render from
      //if (_metadata.GeometryFieldsMetadata.Length > 1)
      //{
      //  foreach (RendererBase r in _renderers)
      //    if (r.SpatialFieldName == null || r.SpatialFieldName == "")
      //      throw new ArgumentException("renderer(s) for {'" + _metadata.Name + "'} with multiple geometry fields, must supply its SpatialFieldName" +
      //                                  "that corresponds to one of feature geometry field names");
      //}
      //else if (_metadata.GeometryFieldsMetadata.Length == 1)
      //{
      //  foreach (RendererBase r in _renderers)
      //    if (r.SpatialFieldName == "")
      //      r.SpatialFieldName = _metadata.GeometryFieldsMetadata[0].Name;
      //      //r.SpatialFieldMetadata = _metadata.GeometryFieldsMetadata[0];

      //    else if (r.SpatialFieldName.ToLower() != _metadata.GeometryFieldsMetadata[0].Name.ToLower())
      //      throw new ArgumentException("invalid field name " + r.SpatialFieldName + " specified in renderer.");
      //}
      //else
      //  throw new ArgumentException("invalid input metadata");

      //// each field name in renderers must exist in metadata
      //foreach (RendererBase r in _renderers)
      //{
      //  bool found = false;
      //  foreach (SpatialFieldMetadata sfm in _metadata.GeometryFieldsMetadata)
      //    if (r.SpatialFieldName.ToLower() == sfm.Name.ToLower())
      //    {
      //      found = true;

      //      // let renderer prepare transforms
      //      //r.SpatialFieldMetadata = sfm;
      //    }

      //  if (!found)
      //    throw new ArgumentException("SpatialFieldName:" + r.SpatialFieldName +
      //                                "not exists in FeatureMetadata");
      //}

      // add style visual attributes to _visualParameters
      foreach (RendererBase r in _renderers)
      {
        r.PrepareToRender();
        r.DataVisualAttributes = VisualAttributes;
        if(r.VisualAttributes != null)
          if(r.VisualAttributes.Count > 0)
            foreach (string name in r.VisualAttributes)
              if (!VisualAttributes.ContainsKey(name))
                VisualAttributes.Add(name, null);

        foreach (string name in r.Style.VisualAttributes)
          if (!VisualAttributes.ContainsKey(name))
            VisualAttributes.Add(name, null);
      }
      if (VisualAttributes.Count > 0)
        _hasVisualAttributes = true;

    }




  }

}
